package com.crm.controller.common;

import com.crm.common.result.AjaxResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/common")
public class FileUploadController {

    // 从配置文件中注入文件存储路径
    @Value("${file.upload-dir:./uploads}")
    private String uploadDir;

    /**
     * 单文件上传
     * @param file 上传的文件
     * @return 成功信息
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 检查文件是否为空
            if (file.isEmpty()) {
                return AjaxResult.error("文件不能为空");
            }


            //文件重命名uuid
            //文件原始名称
            String originalFileName = file.getOriginalFilename();
            //文件后缀
            String extension = originalFileName.substring(originalFileName.lastIndexOf("."));
            //文件重命名
            String objectName = UUID.randomUUID().toString() + extension;

            // 2. 对文件名进行标准化处理，防止路径遍历攻击
            String fileName = StringUtils.cleanPath(objectName);

            // 3. 构造目标路径
            Path targetLocation = Paths.get(uploadDir).toAbsolutePath().normalize().resolve(fileName);

            // 4. 确保目标目录存在
            Files.createDirectories(targetLocation.getParent());

            // 5. 将文件复制到目标位置（替换已存在的文件）
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 6. 返回文件上传成功信息
               //文件存放路径
               String filePath = uploadDir + "/" + fileName;

            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", filePath);
            ajax.put("fileName", filePath);
            //ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());

            return ajax;

        } catch (IOException e) {
            return AjaxResult.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 多文件上传
     * @param files 上传的文件数组
     * @return 成功信息列表
     */
    @PostMapping("/upload/multiple")
    public ResponseEntity<List<String>> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        List<String> results = new ArrayList<>();
        for (MultipartFile file : files) {
            try {
                // ... 重复单文件上传的逻辑 ...
                String fileName = StringUtils.cleanPath(file.getOriginalFilename());
                Path targetLocation = Paths.get(uploadDir).resolve(fileName);
                Files.createDirectories(targetLocation.getParent());
                Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
                results.add("文件上传成功: " + fileName);
            } catch (IOException e) {
                results.add("文件上传失败 [" + file.getOriginalFilename() + "]: " + e.getMessage());
            }
        }
        return ResponseEntity.ok(results);
    }

    /**
     * 文件下载
     * @param fileName 要下载的文件名
     * @return 包含文件数据的 ResponseEntity
     */
    @GetMapping("/download/{fileName:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
        try {
            Path filePath = Paths.get(uploadDir).toAbsolutePath().normalize().resolve(fileName).normalize();
            Resource resource = new UrlResource(filePath.toUri());

            // 检查资源是否存在且可读
            if (resource.exists() && resource.isReadable()) {
                // 确定 Content-Type
                String contentType = determineContentType(fileName);

                return ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType(contentType))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (MalformedURLException e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    /**
     * 根据文件名简单判断 Content-Type
     * 在实际应用中，可以使用更复杂的方法（如使用 Files.probeContentType）
     */
    private String determineContentType(String fileName) {
        // 这是一个非常简单的示例，实际应根据文件扩展名映射
        if (fileName.toLowerCase().endsWith(".pdf")) {
            return "application/pdf";
        } else if (fileName.toLowerCase().endsWith(".jpg") || fileName.toLowerCase().endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (fileName.toLowerCase().endsWith(".png")) {
            return "image/png";
        } else if (fileName.toLowerCase().endsWith(".txt")) {
            return "text/plain";
        } else {
            // 默认设置为二进制流，浏览器会触发下载
            return "application/octet-stream";
        }
    }
}
